package com.atguigu.spzx.manager.service.impl;
import com.atguigu.spzx.manager.interceptor.LoginAuthInterceptor;
import com.atguigu.spzx.manager.mapper.SysMenuMapper;
import com.atguigu.spzx.manager.service.SysMenuService;
import com.atguigu.spzx.model.entity.sys.SysMenu;
import com.atguigu.spzx.model.exception.SpzxException;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.model.vo.sys.SysMenuVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl implements SysMenuService {
    @Resource
    SysMenuMapper sysMenuMapper;

    @Override
    public List<SysMenu> listNestedMenus() {
        //自关联表，组合查询所有数据时，关联查询效率较差
        //可以查询整张表所有数据，在代码中组装
        List<SysMenu> sysMenus = sysMenuMapper.selectAll();
        //组装数据：
        //1、挑选一级菜单: map()可以将集合中的每个对象转为另一个类型的对象返回  collect(Collectors.toXXX)将stream流转为集合对象
        // filter(): 遍历每个对象根据判断条件决定是否保留  reduce():计算  get()用来获取计算的结果
        //  挑选parentId=0的菜单集合：一级菜单集合
        List<SysMenu> parents = sysMenus.stream()
                .filter(sysMenu -> sysMenu.getParentId().longValue() == 0)
                .collect(Collectors.toList());
        //2、为每个一级菜单设置二级菜单
//        parents.forEach(parent->{
//            List<SysMenu> children =sysMenus.stream()
//                    .filter(sysMenu -> parent.getId().longValue() == sysMenu.getParentId().longValue())
//                    .collect(Collectors.toList());
//            //如果子菜单集合不为空 设置给一级菜单
//            if(!CollectionUtils.isEmpty(children)){
//                parent.setChildren(children);
//            }
//        });
        //可以使用递归优化：为1级查找二级菜单，为二级查找三级菜单设置，知道下一级菜单为空 结束递归
        buildMenuTree(parents,sysMenus);
        return parents;
    }

    @Override
    public void delete(Long id) {
        //判断是否能删除
        Long count = sysMenuMapper.selectChildrenCountById(id);
        if(count>0){
            throw new SpzxException(ResultCodeEnum.MENU_DELETE_ERROR);
        }
        //删除
        sysMenuMapper.deleteById(id);

    }

    @Override
    public void save(SysMenu sysMenu) {
        sysMenuMapper.save(sysMenu);
    }

    @Override
    public void update(SysMenu sysMenu) {
        //更新时：菜单的名称不能和 与他在同一级的其他菜单名称相同
        //1、查询和自己在同一级下的其他菜单 但是id和自己不同的 有没有标题重复的
        Long count = sysMenuMapper.selectCountByTitle(sysMenu);
        if(count>0){
            throw new SpzxException(ResultCodeEnum.MENU_TITLE_EXIST_ERROR);
        }
        //2、没有冲突的  则更新菜单
        sysMenuMapper.update(sysMenu);
    }

    @Override
    public SysMenu getById(Long id) {
        return sysMenuMapper.selectById(id);
    }

    @Override
    public Map<String, Object> listMenusAndAssignedMenuId(Long roleId) {
        //查询所有未删除 并且可用的菜单集合
        List<SysMenu> sysMenus = sysMenuMapper.selectAll().stream()
                .filter(sysMenu -> sysMenu.getStatus().intValue() == 1).collect(Collectors.toList());
        //查询roleId已分配的菜单id
        List<Long> assignedMenuIds = sysMenuMapper.selectByRoleId(roleId);
        //获取一级菜单集合
        List<SysMenu> parents = sysMenus.stream().filter(sysMenu -> sysMenu.getParentId().longValue() == 0).collect(Collectors.toList());
        buildMenuTree(parents,sysMenus);
        Map<String, Object> map = new HashMap<>();
        map.put("menus",parents);
        map.put("menuIds",assignedMenuIds);
        return map;
    }

    @Override
    public List<SysMenuVO> listUserMenu() {
        Long userId = LoginAuthInterceptor.getSysUser().getId();
        // user->role->menu
        List<SysMenu> sysMenus = sysMenuMapper.listUserMenu(userId);
        //数据组装
        List<SysMenu> parents = sysMenus.stream().filter(sysMenu -> sysMenu.getParentId().longValue() == 0).collect(Collectors.toList());
        buildMenuTree(parents,sysMenus);
        //将parents所有的sysMenu转为SysMenuVO
        List<SysMenuVO> sysMenuVOParents = parents.stream().map(parent -> {
            //将一级菜单转为sysMenuVO
            SysMenuVO sysMenuVOParent = new SysMenuVO();
            sysMenuVOParent.setName(parent.getComponent());
            //遍历二级菜单转为sysMenuVo集合
            List<SysMenu> children = parent.getChildren();
            if (!CollectionUtils.isEmpty(children)) {
                List<SysMenuVO> sysMenuVOChildren = children.stream().map(child -> {
                    SysMenuVO sysMenuVOChild = new SysMenuVO();
                    sysMenuVOChild.setName(child.getComponent());
                    return sysMenuVOChild;
                }).collect(Collectors.toList());
                sysMenuVOParent.setChildren(sysMenuVOChildren);
            }
            return sysMenuVOParent;
        }).collect(Collectors.toList());
        return sysMenuVOParents;
    }

    private void buildMenuTree(List<SysMenu> parents , List<SysMenu> sysMenus){
        if(CollectionUtils.isEmpty(parents)){
            //父菜单为空 结束递归
            return;
        }
        parents.forEach(parent->{
            List<SysMenu> children =sysMenus.stream()
                    .filter(sysMenu -> parent.getId().longValue() == sysMenu.getParentId().longValue())
                    .collect(Collectors.toList());
            //如果子菜单集合不为空 设置给一级菜单
            if(!CollectionUtils.isEmpty(children)){
                parent.setChildren(children);
                //如果children不为空，以children当做父菜单集合，继续查找他的下一级菜单设置
                buildMenuTree(children , sysMenus);
            }
        });
    }

}
